/* 
 * File:   GameControl.cpp
 * Copyright (C) 2008, 2009
 *		Sergio Padrino Recio (PadrinatoR)
 *
 * Created on 18 de octubre de 2008, 18:32
 *
 * This file is part of BombProject.
 * 
 * BombProject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
   
 * BombProject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with BombProject.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "GameControl.h"
#include "ConfigurationFile.h"
#include <assert.h>

//----------------- STATIC STUFF -----------------

/**
 * Array containing every configured control for the game.
 */
GameControl GameControl::mControls[MAX_CONTROLS];

/**
 * Array containing the global state of every button.
 */
ButtonState GameControl::mGlobalButtonState[NUM_BUTTONS];

void GameControl::initGameControls() {
}

/**
 * Loads the game controls configuration from a configuration file.
 * @param filename File containing the game controls configuration.
 */
void GameControl::loadGameControls(string filename) {
	clearAll();

	ConfigurationFile config;

	if(!config.loadFile(filename)) {
		fprintf(stderr, "GameControl::loadGameControls - configuration file %s couldn't be read\n", filename.c_str());
		return;
	}

	char button_name[20] = "";
	DeviceButtonInfo info;

	for(int i = 0; i < MAX_CONTROLS; i++) {
		for(int j = 0; j < NUM_BUTTONS; j++) {
			sprintf(button_name, "button_%d_%d", i, j);

			config.getButtonInfo(button_name, info);

			mControls[i].setButtonInfo((ButtonID) j, info);
		}
	}
}

/**
 * Saves the game controls configuration into a configuration file.
 * @param filename File that will contain the game controls configuration.
 */
void GameControl::saveGameControls(string filename) {
	SDL_RWops *file = SDL_RWFromFile(filename.c_str(), "w");

	if (file == NULL) {
		fprintf(stderr, "GameControl::saveGameControls - file %s couldn't be opened\n", filename.c_str());
		return;
	}

	string result = "";
	char line[256] = "";
	DeviceButtonInfo info;

	for(int i = 0; i < MAX_CONTROLS; i++) {
		for(int j = 0; j < NUM_BUTTONS; j++) {
			if(mControls[i].getButtonState((ButtonID) j) == NULL) continue;
			
			info = mControls[i].getButtonInfo((ButtonID) j);

			sprintf(line, "button_%d_%d=%d,%d,%d\n", i, j, info.button_code, info.device_type, info.device_index);

			result += string(line);
		}
	}

	if(SDL_RWwrite(file, result.c_str(), 1, result.length()) == -1) {
		fprintf(stderr, "GameControl::saveGameControls - data couldn't be written\n");
	}

	SDL_RWclose(file);

	return;
}


/**
 * Returns a game control.
 * @param index Index of the game control to be returned.
 * @return Game control.
 */
GameControl* GameControl::getGameControl(Uint8 index) {
	assert(index < MAX_CONTROLS);
	
	return &(mControls[index]);
}

/**
 * Updates a global button state for each button from every game control. This lets us know whether a button was pressed by any player or not.
 */
void GameControl::updateGlobalButtonState() {
	for(int j = 0; j < NUM_BUTTONS; j++) {
		mGlobalButtonState[j].button_down = mGlobalButtonState[j].button_held = mGlobalButtonState[j].button_up = 0;
		
	    for(int i = 0; i < MAX_CONTROLS; i++) {
			ButtonState* button = mControls[i].getButtonState((ButtonID) j);
			
			if(button == NULL) continue;
			
			mGlobalButtonState[j].button_down |= button->button_down;
			mGlobalButtonState[j].button_held |= button->button_held;
			mGlobalButtonState[j].button_up |= button->button_up;
		}
	}
}

/**
 * Returns the global button state of a given button.
 * @param id Identifier of the button to be checked.
 * @return The <b>global</b> state of the specified button.
 */
ButtonState* GameControl::getGlobalButtonState(ButtonID id) {
	return &(mGlobalButtonState[id]);
}

/**
 * Clears the configuration of every game control.
 */
void GameControl::clearAll() {
	for(int i = 0; i < MAX_CONTROLS; i++)
		mControls[i].clear();
}

//--------------- NON-STATIC STUFF ---------------

/**
 * Constructor.
 */
GameControl::GameControl() {
	for(int i = 0; i < NUM_BUTTONS; i++) {
		mButtonState[i] = NULL;
	}
}

/**
 * Destructor.
 */
GameControl::~GameControl() {

}

/**
 * Returns the state of a given button.
 * @param id Index of the button to be checked.
 * @return The state of the specified button.
 */
ButtonState* GameControl::getButtonState(ButtonID id) {
	return mButtonState[id];
}

/**
 * Returns the information related to a given button.
 * @param id Index of the button to be checked.
 * @return The information related to the specified button.
 */
DeviceButtonInfo GameControl::getButtonInfo(ButtonID id) {
	return mButtonInfo[id];
}

/**
 * Sets the information related to a given button in order to get a permanent pointer to its state.
 * @param id Index of the button.
 * @param info Button's information.
 */
void GameControl::setButtonInfo(ButtonID id, DeviceButtonInfo& info) {
	mButtonInfo[id] = info;

	mButtonState[id] = gInputHandler->getLinkFromButtonInfo(info);
}

/**
 * Clears the configuration of the game control.
 */
void GameControl::clear() {
	for(int i = 0; i < NUM_BUTTONS; i++)
		mButtonState[i] = NULL;
}
